No caso, como eu disse, seria apenas 1 tabela para os atores. Pelas informações que você passou, eu considerei que a única diferença entre eles era realmente o tipo.
Mas tudo bem, entendi que você tem 3 estruturas distintas pra cada um desses atores, certo?
Nesse caso o mais simples seria acrescentar uma coluna "tipo_ator" na tabela mensagem (e na mensagens_destinos, caso seja seu caso - multi destinatarios), com um código FIXO por cada tipo possível. Sugestão: C, F e U.
O "problema" agora chegou no ponto que você questionou, que você pode resolver tranquilamente com um union ou com um IF (na verdade não lembro como funciona o IF no mysql, então o garantido seria o union). Dá um saque:
select m.*, c.nome_cliente from mensagem m, cliente c where m.tipo_ator = 'C' and m.id_ator = c.id_cliente union
select m.*, u.nome_usuario from mensagem m, usuario u where m.tipo_ator = 'U' and m.id_ator = u.id_usuario union
select m.*, f.nome_fornecedor from mensagem m, fornecedor f where m.tipo_ator = 'F' and m.id_ator = f.id_fornecedor
Pra esse solução você precisa criar um índice em mensagem.tipo_ator pra evitar full table accesses desnecessários. Não vai ficar lento, confia.
Ah, claro que você pode optar também por fazer selects externos de acordo com o tipo do ator, nas tabelas específicas.
Ps.: Você REALMENTE precisa dessas entidades separadas? Eles compartilham assim tão poucas informações?
Porquê você pode ter a tabela pai ator com todas as informações compartilhadas (nome, login, email, data_criacao, etc etc etc) e filhas com as informações específicas de cada um (fornecedor = cnpj, cliente = cpf, etc)