I think something like
(ID {!$ID.text.equals("_")}?)
should do it (if you are using Java as target language). Otherwise you will have to write that semantic predicate in a way that your language understands it.
In short, this will check whether the text does not equal "_" and only then will the subrule match.
Another possible way to do this:
id: ID
| '_'
;
ID: // lexer rule to match every valid identifier EXCEPT '_' ;
That way, whenever you mean "either '_' or any other ID", you use id to match this, if you disallow "_", you can use _.