... it always performs the join even if there is no second element.
By this, I think you mean that there is a '_' present in all cases, even if it the last (and dangling) character in the unpack-ed string.
I tried essentially the same code as jethro under ActiveState 5.8.9 and Strawberries 18.104.22.168, 22.214.171.124 and 126.96.36.199 and get no extraneous underscore.
>perl -wMstrict -le
"my $p = 'ABCDabcdABCDabcd' . pack 'V', 0x3039;
my $unp = join '_', unpack 'H32V*', $p;
$p = 'ABCDabcdABCDabcd';
$unp = join '_', unpack 'H32V*', $p;
Can you supply a short, stand-alone code example that demonstrates the effect you seek to avoid?