It's fundamentally the same attack as the plaintext case, although here it's breaking signature verification.
Here, the computation is
real_sig := Sign(msg)
Cmp(real_sig, provided_sig)
For a fixed message, Sign(msg) is constant time. So, with enough attempts you can create a high-resolution timer to tease apart subtle timing differences in Cmp.
You're correct that if the computation is
provided_hash := Hash(pepper + pw + salt)
Cmp(real_hash, provided_hash)
then the comparison is Hard (tm) to break.
(But this relies upon transmitting the plaintext password, you might say! If you transmit the hash directly, then you're again hosed. One option I've seen previously is transmitting a hash of the password, then hashing + salting it once more, which relies on avalanche effect as you suggest. I provide no guarantees re: the security of such an approach, though -- talk to an actual cryptographer!)