Como eu posso criar uma função que copia uma lista encadeada para outra lista encadeada (excluindo os elementos repetidos)?

/* Eu preciso criar uma função que copie uma lista encadeada passada como parâmetro para outra lista encadeada (exceto os elementos repetidos, se existirem).

#include <stdio.h>
#include <malloc.h>
#define true 1
#define false 0

typedef int bool;
typedef int TIPOCHAVE;

typedef struct {
  TIPOCHAVE chave;
  // outros campos...
} REGISTRO;

typedef struct tempRegistro {
  REGISTRO reg;
  struct tempRegistro* prox;
} ELEMENTO;

typedef ELEMENTO* PONT;

typedef struct {
    PONT inicio;
} LISTA;

//--------------------- PROTÓTIPOS DAS FUNÇÕES --------------------//
void inicializarLista(LISTA* l);
void exibirLista(LISTA* l);
PONT buscaSequencial(LISTA* l, TIPOCHAVE ch);
PONT buscaSeqOrd(LISTA* l, TIPOCHAVE ch);
PONT buscaSeqExc(LISTA* l, TIPOCHAVE ch, PONT* ant);
bool inserirElemListaOrd(LISTA* l, REGISTRO reg);
LISTA copiaLista(LISTA* l);

//--------------------- MAIN --------------------//
int main() {
    //Criação da lista de números que sera copiada	
    LISTA listaPrincipal;
    inicializarLista(&listaPrincipal);
    //Inserção dos números na lista
    REGISTRO reg;
    reg.chave = 5;
    inserirElemListaOrd(&listaPrincipal, reg);
    reg.chave = 15;
    inserirElemListaOrd(&listaPrincipal, reg);
    reg.chave = 25;
    inserirElemListaOrd(&listaPrincipal, reg);
    reg.chave = 3;
    inserirElemListaOrd(&listaPrincipal, reg);
    reg.chave = 12;
    inserirElemListaOrd(&listaPrincipal, reg);
    reg.chave = 11;
    inserirElemListaOrd(&listaPrincipal, reg);
    reg.chave = 23;
    inserirElemListaOrd(&listaPrincipal, reg);
    reg.chave = 29;
    inserirElemListaOrd(&listaPrincipal, reg);
    exibirLista(&listaPrincipal);
  
    //Criação da lista que recebera os elementos da lista principal (exceto os repetidos)
    LISTA listaCopia;
    inicializarLista(&listaCopia);
    listaCopia = copiaLista(&listaCopia);
    exibirLista(&listaCopia);

    system("pause > nul");  
    return 0;
}

//--------------------- IMPLEMENTAÇÃO DAS FUNÇÕES --------------------//
/* Inicialização da lista ligada (a lista jah esta criada e eh apontada 
pelo endereco em l) */
void inicializarLista(LISTA* l) {
    l->inicio = NULL;
} /* inicializarLista */

/* Exibição da lista seqüencial */
void exibirLista(LISTA* l) {
    PONT end = l->inicio;
    printf("Lista: \" ");
    while(end != NULL) {
	    printf("%d ", end->reg.chave); // soh lembrando TIPOCHAVE = int
	    end = end->prox;
    }
    printf("\"\n");
} /* exibirLista */ 

/* Busca sequencial (lista ordenada ou nao) */
PONT buscaSequencial(LISTA* l, TIPOCHAVE ch) {
    PONT pos = l->inicio;
    while(pos != NULL) {
	    if(pos->reg.chave == ch) return pos;
	    pos = pos->prox;
    }
    return NULL;
} /* buscaSequencial */


/* Busca sequencial (lista ordenada) */
PONT buscaSeqOrd(LISTA* l, TIPOCHAVE ch) {
    PONT pos = l->inicio;
    while(pos != NULL && pos->reg.chave < ch) {
	    pos = pos->prox;
    }
    if(pos != NULL && pos->reg.chave == ch) {
	    return pos;	
    }else {
	    return NULL;
    }
} /* buscaSequencial */

/* Busca sequencial - funcao de exclusao (retorna no endereço *ant o indice do
   elemento anterior ao elemento que está sendo buscado [ant recebe o elemento
   anterior independente do elemento buscado ser ou não encontrado]) */
PONT buscaSeqExc(LISTA* l, TIPOCHAVE ch, PONT* ant) {
    *ant = NULL;
    PONT atual = l->inicio;
    while (atual != NULL && atual->reg.chave<ch) {
	    *ant = atual;
	    atual = atual->prox;
    }
    if ((atual != NULL) && (atual->reg.chave == ch)) return atual;
    return NULL;
}
/* buscaSequencialExc */

/* Inserção em lista ordenada sem duplicação */
bool inserirElemListaOrd(LISTA* l, REGISTRO reg) {
    TIPOCHAVE ch = reg.chave;
    PONT ant, i;
    i = buscaSeqExc(l,ch,&ant);
    if(i != NULL) return false;
    i = (PONT) malloc(sizeof(ELEMENTO));
    i->reg = reg;
    if(ant == NULL) { // o novo elemento serah o 1o da lista
	    i->prox = l->inicio;
	    l->inicio = i;
    }else {  // inserção após um elemento já existente
	    i->prox = ant->prox;
	    ant->prox = i;
    }  
    return true;
} /* inserirElemListaOrd */

/* Copia uma lista passada como parametro para outra lista (excluindo os repetidos) */
LISTA copiaLista(LISTA* l) {
    REGISTRO reg;
    LISTA listaCopia;

    TIPOCHAVE ch = reg.chave;
    PONT ant, i;
    i = buscaSeqExc(l, ch, &ant);
    i = (PONT) malloc(sizeof(ELEMENTO));
    i->reg = reg;
    if(ant == NULL) { // o novo elemento serah o 1o da lista
	    i->prox = l->inicio;
	    l->inicio = i;
    }else {  // inserção após um elemento já existente
	    i->prox = ant->prox;
	    ant->prox = i;
    }
    return listaCopia;
} /* copiaLista */