Вы действительно забыли создать хеш!
my @arr = keys %{ +{ map { $_ => 1 } grep /foo/, $str =~ /\b(\w+)\b/g } };
Но есть лучший способ избавиться от дубликатов.
my %seen;
my @arr = grep !$seen{$_}++, grep /foo/, $str =~ /\b(\w+)\b/g;
или
sub uniq { my %seen; grep !$seen{$_}++, @_ }
my @arr = uniq grep /foo/, $str =~ /\b(\w+)\b/g;
или
use List::Util qw( uniq );
my @arr = uniq grep /foo/, $str =~ /\b(\w+)\b/g;
Кстати,
grep /foo/, $str =~ /\b(\w+)\b/g
можно упростить до
$str =~ /\b\w*foo\w*+/g