Invisibility is like density in which by itself its very limited. If you wanted to make only certain objects pass threw each other using density alone you couldn't without a weird work around. Although because of the procs you can make modifications to make density irrelevant. When invisibility isn't enough there's no proc to override and I believe that is the problem. If there was a proc like Cansee (Name up for debate...) that we could override to make exceptions there wouldn't be a problem.
mob
Cansee(Saw)
if(istype(Saw,/mob/Ghost)&&!istype(src,/mob/Ghost))
return 0
return ..()
Ghost
Cansee could be triggered whenever something comes into view. It would only be called if it was overridden though. There are problems with this method such as what to do if something switches from invisible to visible.
The main idea is to add sight procs that can be modified.
Also, you can use the see_invisible variable in conjunction with the invisibility variable to whip up something similar.